'''
Abilities are extra actions (usually a subclass of an existing
Action) the character may take.

The may be available only under certain conditions.
They're usually only usable once per level/map.
'''
import random

from xml.etree import ElementTree

from gamelib import actions, items

abilities = {}
def add_ability(klass):
    abilities[klass.type] = klass

def from_xml(tag):
    '''Load the item from an XML file.
    '''
    type = tag.get('type')
    return abilities[type]()


class Ability(object):
    # Abilities are always Actions.
    # Subclasses must set type to something unique as it's the key rather than
    # type:name
    # type = 'ability'

    used_this_level = False
    used_this_turn = False

    def used(self):
        '''Called when the ability has been used.
        '''
        self.used_this_level = self.used_this_turn = True

    def start_new_level(self, level):
        '''This is invoked when a level has just been initialised.

        "level" is a gamelib.level.Level instance.
        '''
        self.used_this_level = False

    def start_new_turn(self, level):
        '''This is invoked when the character is starting a new turn.

        "level" is a gamelib.level.Level instance.
        '''
        self.used_this_turn = False
    
    def to_xml(self, root):
        m = ElementTree.SubElement(root, 'ability', type=self.type)
        m.tail = '\n'


class SuperStrike(actions.MeleeAttack, Ability):
    '''Quad-damage melee hit. Costs one more AP (max 5) to use.

    Not expended if the hit doesn't connect.
    '''
    type = 'super_strike'
    name = 'super_strike'    # this will be overridden in check()

    def __init__(self):
        pass

    def check(self, level, character, cell, other):
        if self.used_this_level:
            return False

        # find appropriate weapon on character
        for item in (character.body.left_hand, character.body.right_hand):
            if isinstance(item, items.MeleeWeapon):
                break
        else:
            return False
        super(SuperStrike, self).__init__(item)

        # re-jig the descriptions
        self.cost = max(5, self.cost + 1)
        self.label = 'Super Strike with %s'%self.weapon.label
        self.description = '''Strike using incredible force with "%s"
            for 4x damage'''%self.weapon.description

        return super(SuperStrike, self).check(level, character, cell, other)

    # XXX custom animation

    def do(self, callback=None):
        if not self.character.use_action_points(self.cost):
            print 'Attack: not enough actions left'
            return False
        self.animate(self.do_hit, callback)

    def do_hit(self):
        if random.random() > self.chance:
            return False
        damage = self.weapon.damage(self.character, self.other)
        damage *= 4
        self.other.apply_damage(damage)
        self.used()
        return True

add_ability(SuperStrike)

